package com.xatz.scanner

import android.content.Context
import android.widget.Toast
import com.symbol.emdk.EMDKManager
import com.symbol.emdk.EMDKManager.FEATURE_TYPE
import com.symbol.emdk.EMDKResults
import com.symbol.emdk.barcode.*
import timber.log.Timber


/**
 * author: tdq
 * date: 2021/7/19
 * description: 扫描封装
 */
object ScannerManger : EMDKManager.EMDKListener, Scanner.StatusListener,
    Scanner.DataListener, BarcodeManager.ScannerConnectionListener {

    // Variables to hold EMDK related objects
    var emdkManager: EMDKManager? = null
    private var barcodeManager: BarcodeManager? = null
    var scanner: Scanner? = null

    var bSoftTriggerSelected = false

    private var mListener: OnScannerResultListener? = null

    interface OnScannerResultListener {
        fun onScannerResult(data: String?, labelType: String)
    }

    fun setOnScannerResultListener(listener: OnScannerResultListener) {
        this.mListener = listener
    }

    fun init(context: Context) {
        try {
            val results = EMDKManager.getEMDKManager(context, this)
            // Check the return status of getEMDKManager() and update the status TextView accordingly.
            if (results.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {
                Timber.d("EMDKManager object request failed!")
            } else {
                Timber.d("EMDKManager object initialization is in progress...")
            }
        } catch (e: Exception) {
            Timber.e(e)
        }

    }

    fun initBarcodeManager(context: Context) {
        // Get the feature object such as BarcodeManager object for accessing the feature.
        barcodeManager =
            emdkManager?.getInstance(EMDKManager.FEATURE_TYPE.BARCODE) as BarcodeManager?
        // Add external scanner connection listener.
        if (barcodeManager == null) {
            Toast.makeText(context, "Barcode scanning is not supported.", Toast.LENGTH_LONG).show()
        } else {
            barcodeManager?.addConnectionListener(this)
        }
        initScanner()
    }

    fun deInitBarcodeManager() {
        if (emdkManager != null) {
            emdkManager?.release(FEATURE_TYPE.BARCODE)
        }
    }

    private fun initScanner(
    ) {
        if (scanner == null) {
            // Get default scanner defined on the device
            scanner = barcodeManager?.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT)
            if (scanner != null) {
                // Implement the DataListener interface and pass the pointer of this object to get the data callbacks.
                scanner?.addDataListener(this)
                // Implement the StatusListener interface and pass the pointer of this object to get the status callbacks.
                scanner?.addStatusListener(this)
                // Hard trigger. When this mode is set, the user has to manually
                // press the trigger on the device after issuing the read call.
                // NOTE: For devices without a hard trigger, use TriggerType.SOFT_ALWAYS.
                scanner?.triggerType = Scanner.TriggerType.HARD
                try {
                    // Enable the scanner
                    // NOTE: After calling enable(), wait for IDLE status before calling other scanner APIs
                    // such as setConfig() or read().
                    scanner?.enable()
                } catch (e: ScannerException) {
                    e.message?.let { Timber.e(it) }
                    deInitScanner()
                }
            } else {
                Timber.e("Failed to initialize the scanner device")
            }
        }
    }

    fun deInitScanner() {
        if (scanner != null) {
            try {
                scanner?.disable()
                scanner?.removeDataListener(this)
                scanner?.removeStatusListener(this)
                scanner?.release()
            } catch (e: Exception) {
                Timber.e(e)
            }
            scanner = null
        }
    }

    override fun onOpened(p0: EMDKManager?) {
        Timber.e("onOpened")
        this.emdkManager = p0
        p0?.let { initBarcodeManager(App.getContext()) }
    }

    override fun onClosed() {
        if (emdkManager != null) {
            emdkManager?.release()
            emdkManager = null
        }
    }

    override fun onStatus(p0: StatusData?) {
        Timber.e(p0?.state?.name)
        when (p0?.state) {
            StatusData.ScannerStates.IDLE -> {

                if (bSoftTriggerSelected) {
                    scanner?.triggerType = Scanner.TriggerType.SOFT_ONCE
                    bSoftTriggerSelected = false
                } else {
                    scanner?.triggerType = Scanner.TriggerType.HARD
                }

                setConfig()
                try {
                    // Starts an asynchronous Scan. The method will NOT turn ON the scanner beam,
                    //but puts it in a  state in which the scanner can be turned on automatically or by pressing a hardware trigger.
                    scanner?.read()
                } catch (e: ScannerException) {
                    Timber.e(e)
                }
            }
            StatusData.ScannerStates.WAITING -> Timber.e("Scanner is waiting")
            StatusData.ScannerStates.SCANNING -> Timber.e("Scanner is scanning...")
            StatusData.ScannerStates.DISABLED -> Timber.e("Scanner is disabled")
            StatusData.ScannerStates.ERROR -> Timber.e("Scanner is error")
            else -> Timber.e("no state")
        }
    }

    private fun setConfig() {
        if (scanner != null) {
            try {
                // Get scanner config
                val config = scanner?.config
                // Enable haptic feedback
                if (config?.isParamSupported("config.scanParams.decodeHapticFeedback") == true) {
                    config.scanParams.decodeHapticFeedback = true
                }
                // Set scanner config
                scanner?.config = config
            } catch (e: ScannerException) {
                Timber.e(e)
            }
        }
    }

    override fun onData(p0: ScanDataCollection?) {
        if (p0 != null && p0.result == ScannerResults.SUCCESS) {
            p0.scanData.forEach {
                val barcodeData = it.data
                val labelType = it.labelType
                Timber.e("$barcodeData---$labelType")
                mListener?.onScannerResult(barcodeData, labelType.toString())
            }
        }
    }

    override fun onConnectionChange(p0: ScannerInfo?, p1: BarcodeManager.ConnectionState?) {
    }

}